﻿using System.Collections.Generic;
using System.IO;
using System.Text;

namespace WikiDoc.Reader
{
    /// <summary>
    /// A text reader that lines can be put back 
    /// </summary>
    /// <remarks>
    /// 本读取器只有在一行一行进行读取时才有效。放回读取器的行在使用 Pick、Read 方法读取都无法读取到。
    /// </remarks>
    public class PutableReader : TextReaderPipe
    {
        /// <summary>
        /// Initializes a new instance of the BufferedReader class.
        /// </summary>
        public PutableReader(TextReader baseReader) : base(baseReader)
        {
        }

        /// <summary>
        /// queue hold the put back lines
        /// </summary>
        protected internal Stack<string> _Stack = new Stack<string>(7);

        /// <summary>
        /// Puts back the specified line into the stream tail.
        /// </summary>
        /// <param name="line">The line.</param>
        public virtual void PutBack(string line)
        {
            _Stack.Push(line);
        }


        /// <summary>
        /// 从当前流中读取一行字符并将数据作为字符串返回。
        /// </summary>
        /// <returns>输入流的下一行，或者如果已读取了所有字符，则为 null。</returns>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.OutOfMemoryException">内存不足，无法为返回的字符串分配缓冲区。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">下一行中的字符数大于 <see cref="F:System.Int32.MaxValue"></see></exception>
        public override string ReadLine()
        {
            string line;

            if (_Stack.Count > 0)
            {
                line = _Stack.Pop();
            }
            else
            {
                line = BaseReader.ReadLine();
            }

            return line;
        }

        /// <summary>
        /// 读取下一行，而不更改读取器状态或字符源。返回下一个可用行，而实际上并不从输入流中读取此行。
        /// </summary>
        /// <returns>下一个要读取行，或者如果没有更多的可用行或此流不支持查找，则为 null。</returns>
        public virtual string PeekLine()
        {
            if (_Stack.Count > 0)
            {
                return _Stack.Peek();
            }

            string line = BaseReader.ReadLine();

            if (line == null)
            {
                return null;
            }

            _Stack.Push(line);
            return line;
        }

        /// <summary>
        /// 读取从当前位置到 TextReader 的结尾的所有字符并将它们作为一个字符串返回。
        /// </summary>
        /// <returns>包含从当前位置到 TextReader 的结尾的所有字符的字符串。</returns>
        /// <exception cref="T:System.IO.IOException">发生 I/O 错误。 </exception>
        /// <exception cref="T:System.OutOfMemoryException">内存不足，无法为返回的字符串分配缓冲区。 </exception>
        /// <exception cref="T:System.ObjectDisposedException"><see cref="T:System.IO.TextReader"></see> 是关闭的。 </exception>
        /// <exception cref="T:System.ArgumentOutOfRangeException">下一行中的字符数大于 <see cref="F:System.Int32.MaxValue"></see></exception>
        public override string ReadToEnd()
        {
            if (_Stack.Count > 0)
            {
                StringBuilder sb = new StringBuilder(1024);

                while (_Stack.Count > 0)
                {
                    sb.AppendLine(_Stack.Pop());
                }

                sb.Append(BaseReader.ReadToEnd());

                return sb.ToString();
            }
            else
            {
                return BaseReader.ReadToEnd();
            }
        }
    }
}